/*** 
 * @_______________#########_______________________ 
 * @______________############_____________________ 
 * @______________#############____________________ 
 * @_____________##__###########___________________ 
 * @____________###__######_#####__________________ 
 * @____________###_#######___####_________________ 
 * @___________###__##########_####________________ 
 * @__________####__###########_####_______________ 
 * @________#####___###########__#####_____________ 
 * @_______######___###_########___#####___________ 
 * @_______#####___###___########___######_________ 
 * @______######___###__###########___######_______ 
 * @_____######___####_##############__######______ 
 * @____#######__#####################_#######_____ 
 * @____#######__##############################____ 
 * @___#######__######_#################_#######___ 
 * @___#######__######_######_#########___######___ 
 * @___#######____##__######___######_____######___ 
 * @___#######________######____#####_____#####____ 
 * @____######________#####_____#####_____####_____ 
 * @_____#####________####______#####_____###______ 
 * @______#####______;###________###______#________ 
 * @________##_______####________####______________ 
 * @
 * @Author: ipk518 121206530@qq.com
 * @Date: 2025-01-21 11:46:18
 * @LastEditors: ipk518 121206530@qq.com
 * @LastEditTime: 2025-02-19 16:13:21
 * @FilePath: /axilite_qspi/src/flash.h
 * @Description: 
 * @************佛祖保佑************
 * @Copyright (c) 2025 by etws@quyujiang, All Rights Reserved. 
 */

// SPDX-License-Identifier: BSD-2-Clause-Views
/*
 * Copyright (c) 2020-2023 The Regents of the University of California
 */

#ifndef FLASH_H
#define FLASH_H

#include <stdint.h>
#include <unistd.h>

#define FLASH_ERASE_REGIONS 2

struct flash_driver;
struct flash_ops;
struct flash_ioc;

struct flash_erase_region_info {
    size_t block_count;
    size_t block_size;
    size_t region_start;
    size_t region_end;
};

struct flash_device {
    const struct flash_driver *driver;
    const struct flash_ops *ops;

    volatile uint8_t *ctrl_reg;
    volatile uint8_t *addr_reg;
    volatile uint8_t *data_reg;

    size_t size;
    int data_width;

    size_t write_buffer_size;
    size_t erase_block_size;

    int protocol;
    int bulk_protocol;

    int read_dummy_cycles;

    int erase_region_count;
    struct flash_erase_region_info erase_region[FLASH_ERASE_REGIONS];
};

struct flash_ioc {
    uint8_t cmd;
    size_t addr;
    size_t len;
    uint8_t *data;
};

struct flash_ops {
    void (*init)(struct flash_device *fdev);
    int (*sector_erase)(struct flash_device *fdev, size_t addr);
    int (*buffered_program)(struct flash_device *fdev, size_t addr, size_t len, const void *src);
};

struct flash_driver {
    int (*init)(struct flash_device *fdev);
    void (*release)(struct flash_device *fdev);
    int (*read)(struct flash_device *fdev, size_t addr, size_t len, void *dest);
    int (*write)(struct flash_device *fdev, size_t addr, size_t len, const void *src);
    int (*erase)(struct flash_device *fdev, size_t addr, size_t len);
    int (*ioctl)(struct flash_device *fdev, uint8_t mode, void *msg);
};

typedef struct{
	uint32_t jedec_id;	/* JEDEC ID */
    
	uint32_t SectSize;		/* Individual sector size or combined sector
				 * size in case of parallel config
				 */
	uint32_t NumSect;		/* Total no. of sectors in one/two
				 * flash devices
				 */
	uint32_t PageSize;		/* Individual page size or
				 * combined page size in case of parallel
				 * config
				 */
	uint32_t NumPage;		/* Total no. of pages in one/two flash
				 * devices
				 */
	uint32_t FlashDeviceSize;	/* This is the size of one flash device
				 * NOT the combination of both devices,
				 * if present
				 */
	uint32_t SectMask;		/* Mask to get sector start address */
	uint8_t NumDie;		/* No. of die forming a single flash */
} FlashInfo;

struct flash_device *flash_open_qspi(int data_width);
void flash_release(struct flash_device *fdev);
int flash_read(struct flash_device *fdev, size_t addr, size_t len, void *dest);
int flash_write(struct flash_device *fdev, size_t addr, size_t len, const void *src);
int flash_erase(struct flash_device *fdev, size_t addr, size_t len);
int flash_ioctl(struct flash_device *fdev, uint8_t mode, void *msg);

#endif /* FLASH_H */
